﻿using Arction.WinForms.Charting;
using Arction.WinForms.Charting.SeriesXY;
using Arction.WinForms.Charting.Views.ViewXY;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ExampleAreaXY
{
    public partial class ExampleAreaXY : Form
    {
        /// <summary>
        /// LightningChart component.
        /// </summary>
        private LightningChartUltimate _chart = null;

        /// <summary>
        /// Area series data.
        /// </summary>
        private System.Collections.Generic.List<double[][]> _data = null;

        public static List<Color> SolidColors = new List<Color> {
            Color.FromArgb(255, 187, 28, 0),
            Color.FromArgb(255, 222, 54, 11),
            Color.FromArgb(255, 199, 86, 10),
            Color.FromArgb(255, 255, 160, 0),
            Color.FromArgb(255, 255, 124, 0)
        };

        public static List<Color> GradientColors = new List<Color> {
            Color.FromArgb((byte)180, SolidColors[0].R, SolidColors[0].G, SolidColors[0].B),
            Color.FromArgb((byte)180, SolidColors[1].R, SolidColors[1].G, SolidColors[1].B),
            Color.FromArgb((byte)180, SolidColors[2].R, SolidColors[2].G, SolidColors[2].B),
            Color.FromArgb((byte)180, SolidColors[3].R, SolidColors[3].G, SolidColors[3].B),
        };

        public ExampleAreaXY()
        {
            InitializeComponent();
            CreateViewChart();
        }

        /// <summary>
        /// Create chart.
        /// </summary>
        private void CreateViewChart()
        {
            _chart = new LightningChartUltimate();

            // Disable rendering, strongly recommended before updating chart properties.
            _chart.BeginUpdate();

            _chart.Parent = this;
            _chart.Dock = DockStyle.Fill;
            _chart.Name = "Area chart";
            _chart.Title.Text = "Area plot";

            // Configure zoom and pan behaviour.
            _chart.ViewXY.ZoomPanOptions.MouseWheelZooming = MouseWheelZooming.Horizontal;
            _chart.ViewXY.ZoomPanOptions.PanDirection = PanDirection.Horizontal;
            _chart.ViewXY.Zoomed += View_Zoomed;

            // Configure x-axis.
            _chart.ViewXY.XAxes[0].ValueType = AxisValueType.Number;
            _chart.ViewXY.XAxes[0].ScrollMode = XAxisScrollMode.None;

            // Configure y-axis.
            _chart.ViewXY.YAxes[0].PanningEnabled = false;

           
            GenerateData(500);
            OverlapLayout();

            // Autoscale view.
            _chart.ViewXY.ZoomToFit();

            // Configure legend.
            _chart.ViewXY.LegendBoxes[0].Position = LegendBoxPositionXY.SegmentBottomRight;

            // Allow chart rendering.
            _chart.EndUpdate();

           
        }

        /// <summary>
        /// Create overlap areas.
        /// </summary>
        private void OverlapLayout()
        {
            for (int i = 0; i < 3; i++)
            {
                AreaSeries series = new AreaSeries(_chart.ViewXY, _chart.ViewXY.XAxes[0], _chart.ViewXY.YAxes[0]);
                series.Fill.Color =GradientColors[i];
                series.Fill.GradientFill = GradientFill.Solid;
                series.Fill.GradientDirection = 90;
                series.LineStyle.Color =SolidColors[4];
                series.LineStyle.Width = 2f;
                series.MouseHighlight = MouseOverHighlight.None;
                series.MouseInteraction = false;
                series.Title.Text = "Series " + (i + 1).ToString();

                double[][] data = _data[i];
                int pointCounter = data.Length;

                AreaSeriesPoint[] values = new AreaSeriesPoint[pointCounter];
                for (int j = 0; j < pointCounter; j++)
                {
                    values[j].X = data[j][0];
                    values[j].Y = data[j][1];
                }

                series.AddValues(values);
                _chart.ViewXY.AreaSeries.Add(series);
            }
        }

        /// <summary>
        /// Generate data to utilize for all series layouts.
        /// </summary>
        /// <param name="pointCounter">Data points count.</param>
        /// <param name="series">Series count.</param>
        private void GenerateData(int pointCounter)
        {
            _data = new System.Collections.Generic.List<double[][]>(3);
            Random rand = new Random();
            _data.Add(CalculateData(rand, pointCounter, 25000.0, 50000.0));
            _data.Add(CalculateData(rand, pointCounter, 18000.0, 30000.0));
            _data.Add(CalculateData(rand, pointCounter, 5000.0, 15000.0));
        }

        /// <summary>
        /// Generate array of data points for one serie.
        /// </summary>
        /// <param name="rand">Points generator.</param>
        /// <param name="pointCounter">Points count.</param>
        /// <param name="minAmplitude">Min y-value for series.</param>
        /// <param name="maxAmplitude">Max y-value for series.</param>
        /// <returns></returns>
        private double[][] CalculateData(Random rand, int pointCounter, double minAmplitude, double maxAmplitude)
        {
            double stepX = 1000 / (pointCounter - 1);

            double prevY = minAmplitude;

            double[][] result = new double[pointCounter][];

            for (int i = 0; i < pointCounter; i++)
            {
                result[i] = new double[2];

                result[i][0] = (double)i * stepX;

                double y = prevY + (rand.NextDouble() - 0.5) * maxAmplitude / 5;

                if (y < minAmplitude / 2)
                    y = minAmplitude;
                if (y > maxAmplitude * 1.5)
                    y = maxAmplitude;

                result[i][1] = y;

                prevY = y;
            }

            return result;
        }

        /// <summary>
        /// Horizontal zooming logic.
        /// </summary>
        /// <param name="sender">ViewXY.</param>
        /// <param name="e">Event arguments.</param>
        private void View_Zoomed(object sender, ZoomedXYEventArgs e)
        {
            double min = 0;
            double max = 1000;

            ViewXY view = _chart.ViewXY;

            double currentMin = view.XAxes[0].Minimum;
            double currentMax = view.XAxes[0].Maximum;

            if (min > currentMin || max < currentMax)
            {
                if (min > currentMin)
                    currentMin = min;
                if (max < currentMax)
                    currentMax = max;

                _chart.BeginUpdate();
                view.XAxes[0].SetRange(currentMin, currentMax);
                _chart.EndUpdate();
            }
        }
    }
}
